
interface JQuery {
    dateRegister(): JQuery;
}


module Sail {

    $.fn.dateRegister = function () {
        //set = set || {};
        const $obj = this;
        //const isDate = $obj.hasClass('date');
        const isDateTime = $obj.hasClass('dateTime');
        const isDateRange = $obj.hasClass('dateRange');

        if ($obj.data("dateSwitcher")) return;

        var setting = {
            handle: $obj.get(0),
            input: $obj.get(0),
            isHasTime: isDateTime,
            boxId: "#" + guid(),
            //topTitle: set.topTitle
        };

        if (isDateRange) {
            var $input = $obj.find("input");
            if ($input.length < 2) {
                console.debug("结构错误");
                return;
            }
            setting = $.extend(setting,
                {
                    startInput: $input.get(0),
                    endInput: $input.get(1)
                });
            $obj.data("dataSwitcher", DateSwitcher.rangePicker(setting));
        } else {
            $obj.data("dataSwitcher", DateSwitcher.datePicker(setting));
        }
    }


    export class DateSwitcher {

        template = {
            DateSwitch: (str: any) => {
                str = $.extend({
                    reduceYear: 'last year',
                    reduceMonth: 'last month',
                    addMonth: 'next month',
                    addYear: 'next year'
                }, str);
                var html = `<a class="reduceYear zqui-calendar-prev-year-btn"  title="${str.reduceYear}"></a>\
                            <a class="reduceMonth zqui-calendar-prev-month-btn" title="${str.reduceMonth}"></a>\
                            <div class="viewDate zqui-calendar-my-select">\
                                <span class="dateYear zqui-calendar-year-select"></span>&nbsp;<span class="dateMonth zqui-calendar-month-select"></span>\
                            </div>\
                            <a class="addMonth zqui-calendar-next-month-btn" title="${str.addMonth}"></a>\
                            <a class="addYear zqui-calendar-next-year-btn" title="${str.addYear}"></a>`;
                return html;
            },
            DateButton:
            '<div class="dateButton zqui-datepicker__btn-group">\
                <a class="dateClear zqui-datepicker__btn" style="display: block;">清空</a>\
                <a class="dateToday zqui-datepicker__btn" style="display: block;">今天</a>\
            </div>',
            TimeBox:
            '<div class="zqui-datepicker__time"><ul class="timeBox" style="display: block;">\
                <li class="time zqui-datepicker__btn">时间</li>\
                <li><input class="hour">:</li>\
                <li><input class="minute">:</li>\
                <li><input class="second"></li>\
            </ul></div>',
            Thead:
            '<thead>\
                <tr>\
                    <th></th>\
                    <th></th>\
                    <th></th>\
                    <th></th>\
                    <th></th>\
                    <th></th>\
                    <th></th>\
                </tr>\
            </thead>',
            TbodyRow:
            '<tr>\
                <td></td>\
                <td></td>\
                <td></td>\
                <td></td>\
                <td></td>\
                <td></td>\
                <td></td>\
            </tr>',
            dateRangeButton:
            '<div class="dateShortCut zqui-input-link">\
                        <a class="recentWeek">最近七天</a>\
                        <a class="thisWeek">本周</a>\
                        <a class="thisMonth">本月</a>\
                        <a class="nextMonth">次月</a>\
                    </div>'
        };

        Week = ['日', '一', '二', '三', '四', '五', '六'];
        Months = ['01月', '02月', '03月', '04月', '05月', '06月', '07月', '08月', '09月', '10月', '11月', '12月'];


        viewDate(y: number, m: number) {
            var date = new Date(y, m - 1, 1);
            var preDate = new Date(y, m - 1, 1).AddMonths(-1);
            var nexDate = new Date(y, m - 1, 1).AddMonths(1);

            var dayOfWeek = date.getDay();
            var dayOfMonth = DateTime.MonthDays(date);
            var preDayOfMonth = DateTime.MonthDays(preDate);

            var dateList: Array<any> = [];


            function range(numStart: number, numEnd: number, year: number, month: number, className?: string): Array<any> {
                var array: Array<any> = [];
                if (!className) className = "";
                while (numStart <= numEnd) {
                    array.push({ Y: year, M: month, D: numStart++, Class: className });
                }
                return array;
            }

            //填充上个月
            dateList.concat(range(preDayOfMonth - dayOfWeek, preDayOfMonth, preDate.getFullYear(), preDate.getMonth() + 1, "zqui-calendar-table_uncheck"));

            //填充当月
            dateList.concat(range(1, dayOfMonth, y, m));

            //填充下个月
            dateList.concat(range(1, 42 - dayOfWeek - dayOfMonth, nexDate.getFullYear(), nexDate.getMonth() + 1, "zqui-calendar-table_uncheck"));


            dateList.push({ Desc: 'choosing month', Y: y, M: m });

            return dateList;
        }


        render(container: any, data: any) {
            if (data.length % 7 !== 0 && data.length === 0) Error('日期数据错误');
            //渲染boxTop 
            var boxTop = $(container).find('.boxTop');
            var currentDate = data[42];
            console.log(data);
            boxTop.find('.dateYear').text(currentDate.Y);
            boxTop.find('.dateMonth').text(this.Months[currentDate.M - 1]).data('index', currentDate.M - 1);
            //渲染table
            $(container).find('td').each((i, v) => {
                if (i >= 42)
                    Error('渲染容器错误');
                $(v).empty();
                $(v).prop("class", data[i].Class);
                $(v).append(`<a class="zqui-calendar-table__date">${data[i].D}</a>`);//css
                $(v).data('date', data[i]);
            });
            //渲染boxBottom
            var boxBottom = $(container).find('.boxBottom');
            var date = new Date();
            boxBottom.find('.hour').val(date.getHours());
            boxBottom.find('.minute').val(date.getMinutes());
            boxBottom.find('.second').val(date.getSeconds());
        }

        //刷新日期数据
        /*m为自然月*/
        refresh(container: any, y: any, m: any) {
            console.debug('refresh');
            var data = this.viewDate(y, m);
            console.log(data);
            this.render(container, data);
        }

        //定位日期
        findLocation($table: any, date: any): JQuery {
            if (typeof (date) === 'number')
                date = new Date(date);
            date = {
                Y: date.getFullYear(),
                M: date.getMonth() + 1,
                D: date.getDate(),
            }
            var $td: JQuery = $();

            $table.find("td").each(function () {
                var data = $(this).data("date");
                if ((data.Y === date.Y && data.M === date.M && data.D == date.D)) {
                    $td = $(this);
                    return false;
                }
            });

            return $td;
        }

        //恢复点击状态
        recoverState(set: any) {
            var $dateBox = $(set.boxId).find('div.dateBox');
            $(set.boxId).find('tbody td').removeClass("zqui-calendar-table_selected");

            if ($dateBox.length === 0) {
                var input = $(set.input).val();
                var date = new Date(input);//"2017-01-24 15:07:20"
                var $table = $(set.boxId).find("table");

                if (input !== "") {
                    this.refresh(set.boxId, date.getFullYear(), date.getMonth() + 1);
                    var $td = this.findLocation($table, date);
                    $td.addClass("zqui-calendar-table_selected");
                }
                else {
                    this.initBox(set);
                }
            }

            if ($dateBox.length === 2) {
                this.recoverState(set.boxLeftSet);
                this.recoverState(set.boxRightSet);
            }
        }

        //初始化日期
        initBox(set: any) {
            var today = new Date();
            var $dateBox = $(set.boxId).find('div.dateBox');
            if ($dateBox.length === 0)
                this.refresh(set.boxId, today.getFullYear(), today.getMonth() + 1);
            if ($dateBox.length === 2) {
                this.refresh($dateBox.get(0), today.getFullYear(), today.getMonth() + 1);
                this.refresh($dateBox.get(1), today.getFullYear(), today.getMonth() + 1);
            }
        }



        //显示弹窗
        //boxId为最为外层容器Id
        open(set: any) {
            this.initBox(set);
            $(set.handle).on('click', () => {
                console.debug('open');
                //this.initBox(set);
                var handle = $(set.handle).get(0);
                //吸附位置
                $(set.boxId).css({
                    left: `${handle.offsetLeft}px`,
                    top: `${handle.offsetTop + handle.offsetHeight}px`
                });

                this.recoverState(set);

                $(set.boxId).show();
                $(set.boxId).find('div.dateBox').show();//显示双日期面板内部box
                event.stopPropagation();
            });
        }

        //关闭弹窗
        //boxId为最为外层容器Id
        close(set: any) {
            $(document).on('click', () => {
                console.debug('close');
                //判断逻辑移至选择函数
                /*                var isDateRange = $(set.boxId).hasClass('dateRangeBox');
                                if (isDateRange) {
                                    var count = 0;
                                    $(set.boxId).find('div.dateBox').each((i, v) => { count += $(v).data('countClick') });
                                    if (count === 2) {
                                        $(set.boxId).hide();
                                        $(set.boxId).find('div.dateBox').data('countClick', 0);
                                    }
                                    console.log(count);
                                }
                                else {
                                    $(set.boxId).hide();
                                    $(set.boxId).find('div.dateBox').data('countClick', 0);
                                }*/
                $(set.boxId).find('div.dateBox').data('countClick', 0);
                $(set.boxId).hide();
            });
            $(set.boxId).on('click', () => event.stopPropagation());
        }

        //选择日期
        //boxId为最为dateBox容器Id
        choose(set: any) {

            $(set.boxId).on('click', 'td', function () {

                var isDateRange = $(set.boxId).closest('div.dateRangeBox').length === 1;
                var date = $(this).data('date');
                var bottom = $(set.boxId).find('.timeBox');

                var dateStr = new Date(date.Y, date.M - 1, date.D).format(set.isHasTime ? 'yyyy-MM-dd HH:mm:ss' : '');

                $(set.input).val(dateStr);
                $(set.input).data('date', date);
                /*//todo:选中样式*/
                $(set.boxId).find("td").removeClass("zqui-calendar-table_selected");
                $(this).addClass("zqui-calendar-table_selected");

                $(set.boxId).data('countClick', 1);
                if (isDateRange) {
                    var wrapBox = $(set.boxId).closest('div.dateRangeBox');
                    var count = 0;
                    wrapBox.find('div.dateBox').each((i, v) => { count += $(v).data('countClick') });
                    if (count === 2) {
                        $(document).trigger('click');
                    }
                    console.log(count);
                }
                else {
                    $(document).trigger('click');
                }
                event.stopPropagation();
            });
        }

        //更改日期
        changeDate(set: any) {
            var _this = this;
            var boxTop = $(set.boxId).find('.boxTop');
            var yearSpan = boxTop.find('.dateYear');
            var monthSpan = boxTop.find('.dateMonth');

            //年份
            boxTop.find('.reduceYear').on('click', () => {
                console.log('--');
                var year = parseInt(yearSpan.text()) - 1;
                yearSpan.text(year);
                _this.refresh(set.boxId, year, monthSpan.data('index') + 1);
                event.stopPropagation();
            });
            boxTop.find('.addYear').on('click', () => {
                console.log('++');
                var year = parseInt(yearSpan.text()) + 1;
                yearSpan.text(year);
                _this.refresh(set.boxId, year, monthSpan.data('index') + 1);
                event.stopPropagation();
            });
            //月份
            boxTop.find('.reduceMonth').on('click', () => {
                console.log('-');
                var index = monthSpan.data('index');
                if (index === 0) {
                    var year = yearSpan.text();
                    yearSpan.text(parseInt(year) - 1);
                    monthSpan.data('index', 11);
                    monthSpan.text(_this.Months[11]);
                    index = 11;
                }
                else {
                    index -= 1;
                    monthSpan.data('index', index);
                    monthSpan.text(_this.Months[index]);
                }
                _this.refresh(set.boxId, parseInt(yearSpan.text()), index + 1);
                event.stopPropagation();
            });
            boxTop.find('.addMonth').on('click', () => {
                console.log('+');
                var index = monthSpan.data('index');
                if (index === 11) {
                    var year = yearSpan.text();
                    yearSpan.text(parseInt(year) + 1);
                    monthSpan.data('index', 0);
                    monthSpan.text(_this.Months[0]);
                    index = 0;
                }
                else {
                    console.debug('wtf');
                    index += 1;
                    monthSpan.data('index', index);
                    monthSpan.text(_this.Months[index]);
                }
                _this.refresh(set.boxId, parseInt(yearSpan.text()), index + 1);
                event.stopPropagation();
            });
        }

        //清除日期
        //boxId为最为dateBox容器Id
        clear(set: any) {
            $(set.boxId).find('.dateClear').on('click', () => {
                $(set.input).val(null);
                var today = new Date();
                //this.refresh(set.boxId, today.getFullYear(), today.getMonth() + 1);
                /*//todo:取消选中样式*/
                $(set.boxId).find("td").removeClass("zqui-calendar-table_selected");
                $(document).trigger('click');
                event.stopPropagation();
            });
        }

        //选择当日
        //boxId为最为dateBox容器Id
        today(set: any) {
            $(set.boxId).find('.dateToday').on('click', () => {
                console.debug('today');
                var today = new Date();
                this.refresh(set.boxId, today.getFullYear(), today.getMonth() + 1);
                $(set.boxId).data('countClick', 1);
                var dateStr = /^(\d{4}\-\d{2}-\d{2})/.exec(today.toISOString())[0];
                if (set.isHasTime) dateStr += " 00:00:00";
                $(set.input).val(dateStr);
                var isDateRange = $(set.boxId).closest('div.dateRangeBox').length === 1;
                console.log(isDateRange);
                if (isDateRange) {
                    var wrapBox = $(set.boxId).closest('div.dateRangeBox');
                    var count = 0;
                    wrapBox.find('div.dateBox').each((i, v) => { count += $(v).data('countClick') });
                    if (count === 2) {
                        $(document).trigger('click');
                    }
                    console.log(count);
                }
                else {
                    $(document).trigger('click');
                }
                event.stopPropagation();
            });
        }

        //boxId为最为外层容器Id
        shortCutButton(set: any) {
            //var __this = this;
            var $div = $(set.boxId).find('div.dateShortCut');
            $div.on('click', "a.recentWeek", () => {
                $(set.startInput).val(new Date().AddDays(-8).format());
                $(set.endInput).val(new Date().AddDays(-1).format());
                $(document).trigger("click");
            }).on('click', "a.thisWeek", () => {
                var today = new Date();
                var dayOfWeek = today.getDay();
                $(set.startInput).val(new Date().AddDays(1 - dayOfWeek).format());
                $(set.endInput).val(new Date().AddDays(7 - dayOfWeek).format());
                $(document).trigger("click");
            }).on("click", "a.thisMonth", () => {
                $(set.startInput).val(new Date().MonthFirst().format());
                $(set.endInput).val(new Date().MonthEnd().format());
                $(document).trigger("click");
            }).on('click', "a.nextMonth", () => {
                $(set.startInput).val(new Date().AddMonths(1).MonthFirst().format());
                $(set.endInput).val(new Date().AddMonths(1).MonthEnd().format());
                $(document).trigger("click");
            });
        }

        bind(set: any) {
            this.changeDate(set);
            this.choose(set);
            this.today(set);
            this.clear(set);
        }

        createTop(topTitle: any) {
            var top = $('<div class="boxTop"></div>').append(this.template.DateSwitch(topTitle));
            top.addClass("zqui-calendar__hd").css("position", "relative");//css
            return top;
        }

        createTable() {
            var table = $('<table class="dateTable"></table>');
            table.addClass("zqui-calendar-table");//css
            var thead = $(this.template.Thead);
            var tbody = $('<tbody></tbody>');
            thead.find('th').each((i, v) => $(v).text(this.Week[i]));
            for (var i = 0; i < 6; i++) {
                tbody.append($(this.template.TbodyRow));
            }
            table.append(thead).append(tbody);
            table = $("<div class='zqui-calendar__bd'></div>").append(table);//css
            return table;
        }

        createBottom(isHasTime: any) {
            var bottom = $('<div class="boxBottom"></div>');
            bottom.addClass("zqui-datepicker__ft");//css
            var $timeBox = $(this.template.TimeBox);
            if (!isHasTime)
                //$timeBox.find("input").attr("readonly",true);
                $timeBox.css("visibility", "hidden");
            bottom.append($timeBox);
            bottom.append(this.template.DateButton);
            return bottom;
        }

        //创建单个日期面板
        dateBox(set: any) {
            var boxId = set.boxId || "dateBox";
            var box = $('<div id=' + boxId.replace('#', '') + ' class="dateBox" style="display:none;"></div>');
            box.addClass("zqui-datepicker zqui-calendar");//css
            box.addClass(set.boxClass);
            box.append(this.createTop(set.topTitle));
            box.append(this.createTable());
            box.append(this.createBottom(set.isHasTime));
            box.data('countClick', 0);
            return box;
        }

        //双日期面板
        dateRangeBox(set: any) {
            var boxId = set.boxId || "dateRangeBox";
            var box = $('<div id=' + boxId.replace('#', '') + ' class="dateRangeBox zqui-datepicker zqui-datepicker_group" style="display:none;"></div>');

            var button = $(this.template.dateRangeButton);
            var boxLeft = this.dateBox({
                boxId: set.boxLeftSet.boxId,
                isHasTime: set.isHasTime,
                boxClass: "startBox",
                topTitle: set.topTitle
            });
            var boxRight = this.dateBox({
                boxId: set.boxRightSet.boxId,
                isHasTime: set.isHasTime,
                boxClass: "endBox",
                topTitle: set.topTitle
            });

            boxLeft.css("float", "left");

            boxRight.css({
                "float": "left",
                "box-shadow": "none",
                "-webkit-box-shadow": "none"
            });

            box.append(boxLeft);
            box.append(boxRight);
            box.append(button);
            //box.data('countClick', 0);
            return box;
        }

        static datePicker(set: any): DateSwitcher {
            if (!set.input || !set.handle)
                console.debug('配置错误');
            var result = new DateSwitcher();
            var dateBox = result.dateBox(set);
            dateBox.css({ "position": "absolute" });
            $('body').append(dateBox);
            result.bind(set);
            result.open(set);
            result.close(set);
            return result;
        }

        static rangePicker(set: any): DateSwitcher {
            if (!set.handle || !set.startInput || !set.endInput) console.debug('配置错误');

            var boxLeftSet = $.extend({}, set, {
                input: set.startInput,
                boxId: "#" + guid()
            });
            var boxRightSet = $.extend({}, set, {
                input: set.endInput,
                boxId: "#" + guid()
            });
            set.boxLeftSet = boxLeftSet;
            set.boxRightSet = boxRightSet;
            var result = new DateSwitcher();

            var dateRangeBox = result.dateRangeBox(set);
            dateRangeBox.css("position", "absolute");//css
            $('body').append(dateRangeBox);
            result.open(set);
            result.close(set);
            result.bind(boxLeftSet);
            result.bind(boxRightSet);
            result.shortCutButton(set);
            return result;
        }



        static register(form: any) {
            if (!form) form = $(document);
            $(form).find("input.date,input.dateTime,div.dateRange").each(function () {
                $(this).dateRegister();
            });
        }
    }
};